/* 
 * File:   newmain.c
 * Author: av
 * originally for pic16f690
 * Created on 2013. augusztus 19., 9:41
 */

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>

typedef unsigned char uchar;
typedef unsigned int uint;
#define RF31_PWRSTATE_READY 01
#define RF31_PWRSTATE_RX 05
#define RF31_Rx_packet_received_interrupt 0x02
#define RF31_PWRSTATE_POWERDOWN 00

#define SDO RD0
#define SDI RD1
#define SCK RD2

#define nSEL RD3
#define nIRQ RD4

#define LED RD5

uchar ItStatus1,ItStatus2;
uchar RF_RXBUF[35];

void to_rx_mode(void);
void rx_reset(void);
void to_ready_mode(void);
uchar spi_read(uchar address);
void send_read_address(uchar i);
uchar read_8bit_data(void);
void spi_write(uchar address, uchar data);
void send_8bit_data(uchar i);
void Write8bitcommand(uchar command);
void RF31_init_parameter(void);
void delay_50ms(void);
void delay_5ms(void);
void delay_1ms(void);
void port_init(void);
void power_on_delay(void);
void Write0( void );
void Write1( void );
void to_sleep_mode(void);

//__CONFIG(0x3F04);

// PIC18F4550 Configuration Bit Settings

// CONFIG1L
#pragma config PLLDIV = 1       // PLL Prescaler Selection bits (No prescale (4 MHz oscillator input drives PLL directly))
#pragma config CPUDIV = OSC1_PLL2// System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
#pragma config USBDIV = 1       // USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes directly from the primary oscillator block with no postscale)

// CONFIG1H
#pragma config FOSC = INTOSCIO_EC// Oscillator Selection bits (Internal oscillator, port function on RA6, EC used by USB (INTIO))
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOR = ON         // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 3         // Brown-out Reset Voltage bits (Minimum setting)
#pragma config VREGEN = OFF     // USB Voltage Regulator Enable bit (USB voltage regulator disabled)

// CONFIG2H
#pragma config WDT = ON         // Watchdog Timer Enable bit (WDT enabled)
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = ON      // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ON      // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config ICPRT = OFF      // Dedicated In-Circuit Debug/Programming Port (ICPORT) Enable bit (ICPORT disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))


// by default the pic starts at 1Mhz clock
#define _XTAL_FREQ 1000000

void mydelay(int i) {
    while(i>100) {
        __delay_ms(100);
        i-=100;
    }
}

//*****************************************************************************
void main()
{
    uchar i, j, chksum;
    //OSCCON = 0X70; // 8M crystal
    //WDTCON = 0X00;
    power_on_delay();
    port_init();
    RF31_init_parameter();
    NOP();
    to_rx_mode();

    //LED=1;
    //mydelay(1000);
    //LED=0;
    //while(1);
    
    while(1) {
        //to_sleep_mode(); //enter sleep mode
        if(!nIRQ)
        {
            ItStatus1 = spi_read(0x03); //read the Interrupt Status1 register
            ItStatus2 = spi_read(0x04);
            send_read_address(0x7f);
            for(i = 0; i<17; i++)
            {
                RF_RXBUF[i] = read_8bit_data();
            }
            chksum = 0;
            for(i=0;i<16;i++)
                chksum += RF_RXBUF[i];
            if(( chksum == RF_RXBUF[16] )&&( RF_RXBUF[0] == 0x30 ))
            {
                LED = 1;
                __delay_ms(50);
                LED = 0;
            }
            rx_reset(); // rx reset

            //LED = 1;
            //delay_50ms();
            //LED = 0;
        }
    }
}

//*****************************************************************************
//-----------------------------------------------------------------------
void Write0( void )
{
 SCK=0;
 NOP();
 SDI=0;
 NOP();
 SCK=1;
 NOP();
}
//-----------------------------------------------------------------------
void Write1( void )
{
 SCK=0;
 NOP();
  SDI=1;
 NOP();
 SCK=1;
 NOP();
}
//-----------------------------------------------------------------------
void Write8bitcommand(uchar command) // keep sel to low
{
 uchar n=8;
 nSEL = 1;
 SCK=0;
 nSEL=0;
 while(n--)
 {
 if(command&0x80)
 Write1();
 else
 Write0();
 command = command << 1;
 }
 SCK=0;
}

//-----------------------------------------------------------------------
void delay_50ms(void)
{
    //Andras
    __delay_ms(50);
    return;
    
    uchar j;
    for(j = 0; j<10; j++)
    {
        delay_5ms();
    }
}
//-----------------------------------------------------------------------
void delay_5ms(void)
{
    //Andras
    __delay_ms(5);
    return;


    int i;
     for(i = 0; i<650; i++) // 85*5
    {
        ;
    }
}
//-----------------------------------------------------------------------
void delay_1ms(void)
{

    //Andras
    __delay_ms(1);
    return;

     uchar i;
    for(i = 0; i<130; i++)
    {
        ;
    }
}
//-----------------------------------------------------------------------
void port_init(void)
{
    ADCON1bits.PCFG=0b1111;

    TRISDbits.RD0 = 1;
    TRISDbits.RD1 = 0;
    TRISDbits.RD2 = 0;
    TRISDbits.RD3 = 0;
    TRISDbits.RD4 = 1;
    TRISDbits.RD5 = 0;

    LED=0;
}

//-----------------------------------------------------------------------
void power_on_delay(void)
{
    uint i;
    for(i = 0; i<1000; i++)
    {
        delay_1ms();
    }
}
//-----------------------------------------------------------------------
uchar spi_read(uchar address)
{
    uchar result;
    send_read_address(address);
    result = read_8bit_data();
    nSEL = 1;
    return(result);
}
//-----------------------------------------------------------------------
void spi_write(uchar address, uchar data)
{
    address |= 0x80;
    Write8bitcommand(address);
    send_8bit_data(data);
    nSEL = 1;
}
//-----------------------------------------------------------------------
void RF31_init_parameter(void)
{
 ItStatus1 = spi_read(0x03); // read status, clear interrupt
 ItStatus2 = spi_read(0x04);
 spi_write(0x06, 0x00); // no wakeup up, lbd,
 spi_write(0x07, RF31_PWRSTATE_READY); // disable lbd, wakeup timer, use internal 32768,xton = 1; in ready mode
 spi_write(0x09, 0x7f); // c = 12.5p
 spi_write(0x0a, 0x05);
 spi_write(0x0b, 0xf4); // gpio0 rx data output
 spi_write(0x0c, 0xfd); // gpio vdd

 spi_write(0x0d, 0xfd); // gpio vdd

 spi_write(0x0e, 0x00); // gpio 0, 1,2 NO OTHER FUNCTION.
 spi_write(0x70, 0x20); // disable manchest
 

 // FSK RX Modem settings
 //ANDRAS spi_write(0x1c, 0x1d); // RATE_24K: // 2.4k
 spi_write(0x1c, 0xab);
 // ANDRAS spi_write(0x20, 0x41); //0x20 calculate from the datasheet = 500*(1+2*down3_bypass)/(2^ndec*RB*(1+enmanch))
 spi_write(0x20, 0x71);
 // ANDRAS spi_write(0x21, 0x60); // 0x21 , rxosr[10--8] = 0; stalltr = (default), ccoff[19:16] = 0;
 spi_write(0x21, 0x40);
 //ANDRAS spi_write(0x22, 0x27); // 0x22 ncoff =5033 = 0x13a9
 spi_write(0x22, 0x34);
 // ANDRAS spi_write(0x23, 0x52); // 0x23
 spi_write(0x23, 0x6e);
 spi_write(0x24, 0x00); // 0x24
 //spi_write(0x25, 0x06); // 0x25
 spi_write(0x25, 0x0c);
 //ANDRAS spi_write(0x1d, 0x00); // enable afc
 spi_write(0x1d, 0x40); // enable afc
 spi_write(0x1e, 0x0a); // enable afc
 //A spi_write(0x2a, 0x1e);
 spi_write(0x2a, 0x24);
 spi_write(0x1f, 0x03); //A
 spi_write(0x69, 0x60); //A

 // PH+FIFO
 spi_write(0x30, 0x8c); // enable packet handler, msb first, enable crc,
 // 0x31 only readable
 spi_write(0x32, 0xff); // 0x32address enable for headere byte 0, 1,2,3, receive header check for byte 0, 1,2,3
 spi_write(0x33, 0x42); // header 3, 2, 1,0 used for head length, fixed packet length, synchronize word length 3, 2,
 spi_write(0x34, 64); // 64 nibble = 32byte preamble
 spi_write(0x35, 0x20); //0x35 need to detect 20bit preamble
 spi_write(0x36, 0x2d); // synchronize word
 spi_write(0x37, 0xd4);
 spi_write(0x38, 0x00);
 spi_write(0x39, 0x00);

 spi_write(0x3f, 's'); // check hearder
 spi_write(0x40, 'o');
 spi_write(0x41, 'n');
 spi_write(0x42, 'g');
 spi_write(0x43, 0xff); // all the bit to be checked
 spi_write(0x44, 0xff); // all the bit to be checked
 spi_write(0x45, 0xff); // all the bit to be checked
 spi_write(0x46, 0xff); // all the bit to be checked
 // 0x56 ---------0x6c ??????????????????????????
 spi_write(0x79, 0x0); // no hopping
 spi_write(0x7a, 0x0); // no hopping
 spi_write(0x71, 0x22); // Gfsk, fd[8] =0, no invert for Tx/Rx data, fifo mode, txclk -->gpio
 spi_write(0x72, 0x50);  // ANDRAS
 spi_write(0x73, 0x0);
 spi_write(0x74, 0x0); // no offset


 //Carrier frequency
spi_write(0x75, 0x53); // frequency set to 434MHz
spi_write(0x76, 0x64); // frequency set to 434MHz
spi_write(0x77, 0x00);// frequency set to 434MHz

 //ANDRAS
 spi_write(0x0d, 0b00001010);

 //while(1) {
 mydelay(500);
 spi_write(0x0e, 0b00000100);
 mydelay(500);
 spi_write(0x0e, 0b00000000);
 //}


}
//-----------------------------------------------------------------------
void send_read_address(uchar i)
{
    i &= 0x7f;
    Write8bitcommand(i);
}
//-----------------------------------------------------------------------
void send_8bit_data(uchar i)
{
    uchar n = 8;
    SCK=0;
    while(n--)
    {
        if(i&0x80)
            Write1();
        else
            Write0();
        i = i << 1;
    }
    SCK=0;
 }
//-----------------------------------------------------------------------
uchar read_8bit_data(void)
{
 uchar Result, i;
 SCK=0;
 Result=0;
 for(i=0;i<8;i++)
 { //read fifo data byte
 Result=Result<<1;
 SCK=1;
 NOP();
 if(SDO)
 {
 Result|=1;
 }
 SCK=0;
 NOP();
 }
 return(Result);
}
//-----------------------------------------------------------------------
void to_rx_mode(void)
{
 to_ready_mode();
 delay_50ms();
 rx_reset();
 NOP();
}
//-----------------------------------------------------------------------
void rx_reset(void)
{
 spi_write(0x07, RF31_PWRSTATE_READY);
 spi_write(0x7e, 17); // threshold for rx almost full, interrupt when 1 byte received
 spi_write(0x08, 0x03); //clear fifo disable multi packet
 spi_write(0x08, 0x00); // clear fifo, disable multi packet
 spi_write(0x07,RF31_PWRSTATE_RX ); // to rx mode
 spi_write(0x05, RF31_Rx_packet_received_interrupt);
 ItStatus1 = spi_read(0x03); //read the Interrupt Status1 register
 ItStatus2 = spi_read(0x04);
}
//-----------------------------------------------------------------------
void to_ready_mode(void)
{
 ItStatus1 = spi_read(0x03);
 ItStatus2 = spi_read(0x04);
 spi_write(0x07, RF31_PWRSTATE_READY);
}
//-----------------------------------------------------------------------
void to_sleep_mode(void)
{
 LED = 0;
 spi_write(0x07, RF31_PWRSTATE_READY);
 ItStatus1 = spi_read(0x03); //read the Interrupt Status1 register
 ItStatus2 = spi_read(0x04);
 spi_write(0x07, RF31_PWRSTATE_POWERDOWN);
 while(1)
 {
 ;
 }
}
//--------------------------------------------------------------
     
